package com.doom.kotlindemo

import com.doom.kotlindemo2.multiply
import java.lang.Exception
import kotlin.math.log



object FADemo {

    fun test() {
        logd<FADemo>("test");

//        val list: List<String> = listOf("1", "2", "3");
//        for(str in list) {
//            logd<FADemo>(str);
//        }

//        list.forEach(Consumer { logd<FADemo>(it) });

//        list.forEach(System.out::println)

//        var sumValue = sum(10, 20);
//        logd<FADemo>("sumValue:${sumValue}");
//        var sum2Value = sum2(10, 20);
//        logd<FADemo>("sum2Value:${sum2Value}");
//
//        myPrint(1, 2)

//        val a: Int = 1 //常量
//        val a = 1
//        a = 2 // N build err: Val cannot be reassigned

//        val b: Byte = 20;
//        var a = 1
//        a = b // N build err: Type mismatch: inferred type is Byte but Int was expected
//        a = b.toInt() // Y

//        var a = multiply(1, 2)
//        logd<FADemo>(a)

//        var x = 10
//        var y = 20
//        var min = if(x < y) x else y
//        var max = if(x < y) y else x
//        var min = if(x < y) {
//            logd<FADemo>("min x < y");
//            x
//        } else {
//            logd<FADemo>("min x >= y");
//            y
//        }
//        var max = if(x < y) {
//            logd<FADemo>("max x < y");
//            y
//        } else {
//            logd<FADemo>("max x >= y");
//            x
//        }
//        logd<FADemo>("min: $min max: $max")

//        var str: String = "xx"
//        try{
//            var value = str.toInt()
//            logd<FADemo>("str.toInt value: " + value)
//        } catch (e: Exception) {
//            e.printStackTrace() // runtime err: java.lang.NumberFormatException: For input string: "xx"
//        }

        // Note: Any 不为 null
//        logd<FADemo>(str2Int("12"))
        //Type mismatch.
        //Required:
        //Any
        //Found:
        //Int?
//        str2Int("12")?.let { logd<FADemo>(it) } // str2Int("12")不为空才执行

//        str2Uppercase("abc")?.let { logd<FADemo>(it) }
//        var result = str2Uppercase(123)
//        if(result != null) {
//            logd<FADemo>(result)
//        }else{
//            logd<FADemo>("is not string")
//        }

//        var intArray = intArrayOf(1, 2, 3)
//        var intArray2: IntArray = intArrayOf(1, 2, 3)
//        logd<FADemo>("size is: "+ intArray2.size)
//
//        for(i in intArray) {
//            logd<FADemo>("$i")
//        }
//
//        for(i in intArray.indices) {
//            logd<FADemo>("$i - ${intArray[i]}")
//        }
//
//        for((i, v) in intArray.withIndex()) {
//            logd<FADemo>("$i - $v")
//        }

//        var value = 33
//        var result = when (value) {
//            1,2 -> { // 不同的取值
//                "1,2"
//            }
//            22 -> {
//                22
//            }
//            in 30..90 -> { //数值范围
//                "88"
//            }
//            else -> {
//                "99"
//            }
//        }
//        logd<FADemo>(result)

        // 范围
//        var a = 1
//        var b = 10
//        if( a !in 2..10){
//        if( a !in 2.rangeTo(10)){
//            logd<FADemo>("<")
//        }else{
//            logd<FADemo>(">")
//        }

//        for(i in 2..10 step 2) {
//        for(i in 10 downTo 2 step 2) {
//            logd<FADemo>(i)
//        }

//        var array = listOf<String>("1", "22", "33")
//        for(i in array) {
//            logd<FADemo>(i)
//        }
//
//        when {
//            "1" in array -> logd<FADemo>(1)
//        }

//        array.filter { it.length > 1 }.map { it.toUpperCase() }.sorted().forEach {logd<FADemo>(it)}

//        var a: String = "hello \n world"
//        logd<FADemo>(a)

//        var a: String = """hello
//            \n world"""
//        logd<FADemo>(a)

        // 对象
        // 一个主构造函数， 一个或多个二级构造函数
        // 主构造函数可以省略： 主构造函数没有任何注解或是可见性关键字修饰
//        var classA1 = classA("admin", 10, "beijing");
//        classA1.printInfo()

//        var classB1 = classB("admin", 10, "beijing");
//        classB1.printInfo()

//        var classD1 = classD();
//        classD1.printInfo()

//        var child = child1()
//        child.name()

//        var child = child1()
//        child.printinfo()

//        var child3var = child3()
//        child3var.name()
//        println(child3var.name)

//        //接口
//        var c = C()
//        c.method()

//        myobject.method()

//        mytest.myobject.method()
//        println(mytest.myobject.a)
//        mytest.method()
//        println(mytest.a)

//        D.func1()
//        D.func2()
//        D.Companion.func1()
//        D.Companion.func2()

//        var classA1 = ClassA()
//        classA1.address = "xxx"
//        println(classA1.address)

//        var classa = ClassA()
//        classa.printinfo()

//        var extensiontest = ExtensionTest()
//        extensiontest.add(1, 2)
//        extensiontest.subtract(2, 1)
//        extensiontest.multiply(2, 2)

//        myPrint(AA()) // a
//        myPrint(BB()) // a

//        var cc = CC()
//        cc.foo() // 扩展名一样会覆盖
////        cc.foo(1)
//
//        var str: String = "yyy"
//        println("dm "+str.toString2())
//
//        var myex1 = myex()
//        println("dm "+ myex1.name)

//        comp.method()

//        var ee = EE()
//        var dd = DD()
////        ee.test()
//        ee.world(dd)

//        var dataclass = DATACLASS("xxx", 1);
//        println(dataclass)
//        var dataclass2 = dataclass.copy(id = 2)
//        println(dataclass2)

        // 解构
//        var (name, id) = dataclass2
//        println("name:$name id:$id")

//        var persion2 = Persion2()
//        println(persion2)

        //密封类 sealed class (类似枚举) 抽象类

    }

    // lombok
//    data class DATACLASS(val name: String, val id: Int) {
//
//    }
//
//    // 需要拥有无参构造方法，需要为所有属性指定默认值
//    data class Persion2(val name: String = "SSS", val id: Int = 2)

    //解构声明 componentN -> 对应各个参数

    // 扩展的作用域
    // 解决辅助类问题
//    class DD {
//        fun method() {
//            println("dm DD method")
//        }
//    }
//
//    class EE {
//        fun method2() {
//            println("dm EE method2")
//        }
//
//        fun DD.hello() {
//            println("dm EE DD.hello")
//            method()
//            method2()
//        }
//
//        fun world(dd: DD){
//           dd.hello()
//        }
//
//        fun DD.output() {
//            println("dm output:"+toString())
//            println("dm output"+this@EE.toString())
//        }
//
//        fun test() {
//            var dd = DD()
//            dd.output()
//        }
//    }
//
//    class comp {
//        companion object coo {
//
//        }
//    }
//
//    fun comp.coo.method() {
//        println("dm coo")
//    }

//
//    class CC {
//        fun foo(){
//            println("foo old")
//        }
//    }
//    fun CC.foo() {
//        println("foo new")
//    }
//
//    fun Any?.toString2(): String {
//        return "xxx"
//    }
//
//    class myex
//    val myex.name: String
//    get() = "hello"



    // 扩展 extension
    // 扩展函数的解析是静态分发的，不是动态的，不支持多态，调用取决于对象的声明类型
//    class ExtensionTest {
//        fun add(a: Int, b: Int) = a + b
//        fun subtract(a: Int, b: Int)  = a - b
//    }
//
//    fun ExtensionTest.multiply(a: Int, b: Int) = a * b
//
//    open class AA
//    class BB: AA()
//
//    fun AA.a() = "a"
//    fun BB.a() = "b"
//
//    fun myPrint(aa: AA) {
//        println(aa.a())
//    }

    //可见修饰符 private protected internal public
    // public 到处可以访问
    // protected 可以被子类访问
    // private 类中，本源文件
    // internal 同模块下可见


    // lateinit 延迟初始化
    // 1. 用在类中声明的var属性
    // 2. 属性不能拥有自定义的setter getter
    // 3. 属性类型非空，不能是原生数据类型
//    class ClassA {
//        lateinit var name: String
//        init {
//            name = "init"
//        }
//        fun printinfo(){
//            println("name:$name")
//        }
//    }

    // var propertyName: propertyType = initializer
    // getter()...
    // setter()...
    //
    // backing field 支撑字段(域)
    // backing property 支撑属性
//    class ClassA {
//        val age: Int = 20
//            get() = 20

//        var address: String = "init"
//            get() {
//                println("address get")
//                return field
//            }
//            set(value) {
//                println("address set")
//                field = value
//            }
//    }

    //对象声明 object declaration
    //单例
    //kotlin推荐使用包级别的函数来作为静态方法
//    object myobject {
//        fun method(){
//            println("myobject method")
//        }
//    }

    //伴生对象 companion object
    //静态变量 静态方法 -> 真实对象的实例成员
    //一个类只允许一个伴生对象
    //如果不提供伴生对象名称，默认名称为Companion
    //JVM 通过@JvmStatic注解来将伴生对象的成员真正成为类的静态方法或属性
//    class mytest {
//        companion object myobject {
//            var a: Int = 10
//            fun method(){
//                println("mytest myobject method")
//            }
//        }
//    }

//    class D {
//        companion object {
//            @JvmStatic
//            fun func1(){
//
//            }
//            fun func2(){
//
//            }
//        }
//    }


//    //抽象类
//    open class basicclass{
//        open fun method(){
//
//        }
//    }
//
//    // 抽象类
//    abstract class childclass: basicclass() {
//        override abstract fun method() //可以使用抽象方法来override父类方法
//    }

    //接口
//    interface A {
//        fun method() {
//            println("interface A method")
//        }
//    }
//
//    open class B {
//        open fun method(){
//            println("class B method")
//        }
//    }
//
//    class C: A, B(){
//        override fun method() {
//            println("C method")
////            super<A>.method() //显示指名父类
////            super<B>.method()
//        }
//    }

//    open class parent3{
//        open fun name(){
//            println("parent3")
//        }
//        open val name: String get()  = "getparent3"
//    }
//
//    class child3: parent3() {
//        override open fun name(){
//            println("child3")
//        }
//        override val name: String get() = super.name + " and child3"
//    }

//    open class parent {
//        open val name: String = "parent"
//
//        fun printinfo(){
//            println(name)
//        }
//    }
//
//    class child1: parent(){
//        override val name: String = "child1"
//    }
//
//    class child2(override val name: String): parent(){
//
//    }



//    open class Parent {
//        open fun name(){
//            println("parent");
//        }
//    }
//
//    class child1: Parent() {
//        override fun name() { // override方法重写, 需要父类方法使用open关键字
//            println("child1")
//        }
//    }



//    //kotlin中所有类默认无法被继承，都是final的
//    open class ClassParent (name: String, age: Int) {
//
//    }
//
//    class ClassChild (name: String, age: Int): ClassParent(name, age){
//
//    }
//
//    // 如果没有主构造，需要次构造函数中使用super关键字初始化父类型
//    class ClassChildA: ClassParent {
//        constructor(name: String, age: Int): super(name, age) {
//        }
//    }
//
//    // 全部参数有默认值，编译器默认生成不带参数的构造函数 -> 调用的时候不需要参数
//    class classD (private val username: String = "user1", private val age: Int = 1, private var address: String = "unknown") { //主构造函数
//
//        fun printInfo() {
//            logd<FADemo>("username: $username age: $age address: $address")
//        }
//    }
//
//    // private constructor
//    // 可见性修饰符 kotlin 默认puclic
//    class classC private constructor(private val username: String, private val age: Int, private var address: String) { //主构造函数
//
//        fun printInfo() {
//            logd<FADemo>("username: $username age: $age address: $address")
//        }
//    }
//
//    //参数中直接定义变量
//    class classB /*constructor*/(private val username: String, private val age: Int, private var address: String) { //主构造函数
//
//        fun printInfo() {
//            logd<FADemo>("username: $username age: $age address: $address")
//        }
//    }
//
//    //类定义
//    // 一个主构造函数， 一个或多个二级构造函数
//    // 主构造函数可以省略： 主构造函数没有任何注解或是可见性关键字修饰
//    class classA /*constructor*/(username: String) { //主构造函数
//
//        private var username: String;
//        private var age: Int;
//        private var address: String;
//
//        //初始化代码块 : 初始化变量
//        init {
//            this.username = username.toUpperCase()
//            this.age = 20;
//            this.address = "shanghai"
//            logd<FADemo>(this.username + this.age + this.address)
//        }
//
//        // 二级构造函数
//        constructor(username: String, age: Int) : this(username) {
//            this.age = age;
//        }
//
//        constructor(username: String, age: Int, address: String) : this(username, age) {
//            this.address = address;
//        }
//
//        fun printInfo() {
//            logd<FADemo>(this.username + this.age + this.address)
//        }
//    }

//    fun sum(a: Int, b: Int): Int {
//        return a + b;
//    }
//
//    fun sum2(a: Int, b: Int) = a + b
//
//    //没有返回值
//    fun myPrint(a: Int, b: Int): Unit {
//        logd<FADemo>("myPrint result is: " + (a + b))
//        //字符串模板
//        logd<FADemo>("$a + $b = ${a + b}")
//    }
//
//    fun str2Int(str: String): Int? { // 返回值可能为null
//        try{
//            return str.toInt()
//        } catch (e: Exception) {
//            return null;
//        }
//    }
//
//    fun str2Uppercase(x: Any): String? {
//        if(x is String) {
//            return x.toUpperCase()
//        }
//        return null
//    }
}

////密封类 （类似与枚举）
//sealed class Calculator
//
//class Add: Calculator()
//
//class Subtrace: Calculator()
//
//class Multiply: Calculator()
//
//fun calculate(a: Int, b: Int, cal: Calculator) = when (cal) {
//    is Add -> a + b
//    is Subtrace -> a - b
//    else -> a * b
//}
//
//fun main(args: Array<String>) {
//    println(calculate(3, 1, Add()))
//    println(calculate(3, 1, Subtrace()))
//    println(calculate(3, 1, Multiply()))
//}

//泛型
class MyGeneric<T>(t: T) {
    var variable: T

    init {
        this.variable = t
    }
}

//泛型 协变covariant 与 逆变controvariant
// 协变 -> 子类型赋给父类型
// 逆变 -> 父类型赋给子类型 (实现子类型互相转化)
//out 读取 Any  ， Producer out ,方法的返回类型
//in 写 . consumer in， 方法的输入参数
//同时 in out ，使用T
// kotlin 声明处协变 java 使用处协变

class MyClass<out T, in M>(t: T, m: M) {
    private var t: T
    private var m: M

    init {
        this.t = t
        this.m = m
    }

    fun get(): T = this.t

    fun set(m: M) {
        this.m = m
    }

//    fun getM(): M = this.m
}

fun myTest(myClass: MyClass<String, Number>) {
    var myObject: MyClass<Any, Int> = myClass
    myObject.set(45)
    println(myObject.get())
//    println(myObject.getM())
}

fun copy(from: Array<out Any>, to: Array<Any>) {
    for(i in from.indices){
        to[i] = from[i];
    }
}

// start projection 星投影

// 泛型函数
fun <T> getValue(item: T): T {
    return item;
}

// List<T> 上界
// Any?
class upupclass<T: List<T>>{

}
// 多个上界
class upup2class<T> where T: Comparable<T>, T: Any {

}

// 内部类 inner - 对应于java的非静态内部类
// 嵌套类 - 对应于java的静态内部类
// 访问外部类比变量的方式：this@outerClass.xxx
//                 java: outerClass.this.xxx
class outerClass {
    private var str: String = "str"

    /*inner*/ class innerClass(){
        fun innermethod() = "inner"
//        fun innermethod() = this@outerClass.str
    }

    fun getname(): String {
        class localnestedclass {
            val name: String = "localnestedclass"
        }
        var localnestedclass1 = localnestedclass()
        return localnestedclass1.name
    }

}

// 对象表达式 object expression
// 为了解决匿名内部类的一些缺陷
interface myinterface11 {
    fun myprint(i: Int) {
        println("myprint $i")
    }
}

abstract class myabstract {
    abstract val age: Int
    abstract fun myabstractfun()
}

// 匿名对象只能在局部变量范围内或是被private修饰的成员变量范围内才能被识别出其真正的类型
class myclass711 {
    private var myobj = object  {
        fun output(){
            println("output")
        }
    }
    fun mytest(){
        println(myobj.javaClass)
        println(myobj::class.java)
        myobj.output()
    }
}

//java匿名内部类-对象表达式

// ENUM 枚举
enum class Season {
    SPRING, SUMER, AUTUMN, WINTER
}
enum class SeasonInt(val temperature: Int) {
    SPRING(0), SUMER(1), AUTUMN(3), WINTER(4)
}

//对象声明
object MyObject {
    fun method() = "hellow myobject"
}

object MyObjectInterface : myinterface11 {
    override fun myprint(i: Int) {
        super.myprint(i)
    }

}

fun main(args: Array<String>) {

    MyObjectInterface.myprint(100)

//    val seasons = Season.values()
//    seasons.forEach { println(it) }
//    val SeasonIntValues = SeasonInt.values()
//    SeasonIntValues.forEach { println(it.temperature) }

//    var myclass711var = myclass711()
//    myclass711var.mytest()

//    var myobj3 = object: myinterface11, myabstract() {
//        override val age: Int
//            get() = 20
//
//        override fun myabstractfun() {
//            println("myabstractfun")
//        }
//    }
//    myobj3.myprint(11)
//    println(myobj3.age)
//    myobj3.myabstractfun()

//
//    var myobj = object: myinterface11 {
//
//    }
//    myobj.myprint(1)

//    var myobj1 = object  {
//        var val1 = "val1"
//        fun myfun() = "myfun"
//    }
//
//    println(myobj1.val1)
//    println(myobj1.myfun())

//    println(outerClass().getname())
    //嵌套
//    println(outerClass.innerClass().innermethod())
    //内部
//    println(outerClass().innerClass().innermethod())

//    val item = getValue(3)
//    println(item)

//    val from: Array<Int> = arrayOf(1, 2, 3, 4)
//    val to: Array<Any> = Array<Any>(4, {"hello" + it})
//    copy(from, to)
//    for (item in to){
//        if(item is String){
//            println("String")
//        }else if(item is Int){
//            println("Int")
//        }
//        println(item)
//    }

//    var myGeneric: MyGeneric<String> = MyGeneric<String>("XXX")
//    var myGeneric = MyGeneric("yyy")
//    println(myGeneric.variable)

//    var myClass = MyClass("dakjf", 3)
//    myTest(myClass as MyClass<String, Number>)
}